package cn.jhs.config.security;

import cn.jhs.config.security.sys.FakeSysmangerServiceImpl;
import cn.jhs.config.security.sys.SysmangerService;
import cn.jhs.config.security.login.mobile_code.MobileCodeAuthenticationProcessingFilter;
import cn.jhs.config.security.login.mobile_code.MobileCodeAuthenticationProvider;
import cn.jhs.config.security.login.username_password.UsernameAuthenticationProcessingFilter;
import cn.jhs.config.security.login.username_password.UsernameAuthenticationProvider;
import cn.jhs.config.security.plugins.MyAuthenticationFailureHandler;
import cn.jhs.config.security.plugins.MyAuthenticationSuccessHandler;
import cn.jhs.config.security.plugins.SimplePasswordEncoder;
import cn.jhs.config.security.plugins.SimpleUserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author Trump
 * @version 1.0.0
 * @ClassName SecurityConfiguration.java
 * @Description spring security 配置
 * @createTime 2019年08月15日 10:23:00
 */
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/js/**", "/fonts/**", "/plugins/**", "/webjars/**");
        web.ignoring().antMatchers("/favicon.ico");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // "/,index" 不需要验证
                .antMatchers("/welcome").permitAll()
                //其他的请求，必须要通过验证后才可以访问
                .anyRequest().authenticated()
//				.anyRequest().access("@myPermissionExtraService.hasPermission(request,authentication)")
                .and()
                //csrf默认开启，这里先显式关闭
//				.csrf().disable()
                //内部注册 UsernamePasswordAuthenticationFilter
                .formLogin()
                //form表单 登录页面url，POST请求url提交地址，默认为/login 用户名，密码参数名
                .loginPage("/login")
                //登录成功handler
//                .successHandler(myAuthenticationSuccessHandler())
//                //登录失败跳转地址
////				.failureForwardUrl("/error")
//                .failureHandler(myAuthenticationFailureHandler())
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/welcome")
                .permitAll();

        http.addFilterBefore(mobileCodeAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(usernameAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public MobileCodeAuthenticationProcessingFilter mobileCodeAuthenticationProcessingFilter() throws Exception {
        MobileCodeAuthenticationProcessingFilter filter = new MobileCodeAuthenticationProcessingFilter();
        filter.setAuthenticationManager(super.authenticationManagerBean());
        filter.setAuthenticationFailureHandler(myAuthenticationFailureHandler());
        filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler());
        return filter;
    }

    @Bean
    public UsernameAuthenticationProcessingFilter usernameAuthenticationProcessingFilter() throws Exception {
        UsernameAuthenticationProcessingFilter filter = new UsernameAuthenticationProcessingFilter();
        filter.setAuthenticationManager(super.authenticationManagerBean());
        filter.setAuthenticationFailureHandler(myAuthenticationFailureHandler());
        filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler());
        return filter;
    }

    @Bean
    public MyAuthenticationSuccessHandler myAuthenticationSuccessHandler() {
        MyAuthenticationSuccessHandler myAuthenticationSuccessHandler = new MyAuthenticationSuccessHandler();
        myAuthenticationSuccessHandler.setDefaultTargetUrl("/success");
        return myAuthenticationSuccessHandler;
    }

    @Bean
    public MyAuthenticationFailureHandler myAuthenticationFailureHandler() {
        return new MyAuthenticationFailureHandler();
    }


    @Bean
    public UserDetailsService simpleUserDetailsServiceImpl() {
        return new SimpleUserDetailsServiceImpl();
    }

    @Bean
    public PasswordEncoder simplePasswordEncoder() {
        return new SimplePasswordEncoder();
    }

    @Bean
    public SysmangerService fakeSysmangerServiceImpl() {
        return new FakeSysmangerServiceImpl();
    }

    @Bean
    public MobileCodeAuthenticationProvider mobileCodeAuthenticationProvider() {
        return new MobileCodeAuthenticationProvider();
    }

    @Bean
    public UsernameAuthenticationProvider usernameAuthenticationProvider() {
        return new UsernameAuthenticationProvider();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(usernameAuthenticationProvider()).authenticationProvider(mobileCodeAuthenticationProvider());
    }
}
